#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>

#include "Manager.h"

Manager* managerConstruct()
{
	Manager *manager;
	manager = (Manager*)malloc(sizeof(Manager));
	return manager;
}

Manager* managerConstructWithShaft(Shaft* shaft)
{
	Manager *manager = managerConstruct();
	manager->shafts = listConstruct(elementConstruct(shaft));
	return manager;
}

void managerDeconstruct(Manager *manager)
{
	if(manager->shafts->count > 0)
	{
		listPrepareForLooping(manager->shafts);
		Element *element;

		while ((element = listNextElement(manager->shafts) != NULL)
		{
			Shaft *shaft = (Shaft*)element->value;
			elevatorDeconstruct(shaft->elevator);
		}
	}

	listDeconstruct(manager->shafts);
	free(manager);
}

void managerAddShaft(Manager *manager, Shaft *shaft)
{
	listAddElement(manager->shafts, elementConstruct(shaft));
}

Shaft* managerSelectShaftForDispatch(Manager *manager, Destination *destination)
{
	if(manager->shafts == NULL)
		return NULL;
	else if (manager->shafts->count == 1)
	{
		Shaft *shaft = (Shaft*)listElementAtIndex(manager->shafts, 0)->value;
		if(destination->floor > shaft->highestFloor || destination->floor < shaft->lowestFloor)
			return NULL;
		else
			return shaft;
	}
	else
	{
		Shaft *currentShaft;
		Shaft *chosenShaft;
		listPrepareForLooping(manager->shafts);
		// BUG: We aint checkin lowestFloor & highestFloor here
		currentShaft = chosenShaft = (Shaft*)listNextElement(manager->shafts)->value;

		while (currentShaft != NULL)
		{
			int currentFloorDifference = currentShaft->elevator->currentFloor < destination->floor
				? destination->floor - currentShaft->elevator->currentFloor
				: currentShaft->elevator->currentFloor - destination->floor;

			int chosenFloorDifference = chosenShaft->elevator->currentFloor < destination->floor
				? destination->floor - chosenShaft->elevator->currentFloor
				: chosenShaft->elevator->currentFloor - destination->floor;

			if (destination->floor <= chosenShaft->highestFloor &&
				destination->floor >= chosenShaft->lowestFloor &&
				currentFloorDifference < chosenFloorDifference)
				currentShaft = chosenShaft;

			Element *element = listNextElement(manager->shafts);
			if(element == NULL)
				currentShaft = NULL;
			else
				currentShaft = (Shaft*)element->value;
		}

		return chosenShaft;
	}
}

void managerSendEventToShaft(Shaft *shaft, elevatorEvent eventToExecute)
{
	shaftSendEvent(shaft, eventToExecute);
}